
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <pthread.h>
#include <libxml/encoding.h>
#include <libxml/xmlwriter.h>
#include <libxml/parser.h>
#include "wget.h"
#include "gpiod.h"
#ifndef SOFTWARE_NAME
#define SOFTWARE_NAME "controller"
#endif
#ifndef VERSION
#define VERSION "NO VERSION"
#endif
#define loop_u_time 200000
struct ts_gpio {
  char *name;
  int chipNum;
  int lineOffset;
  int value;
  void *chip;
  void *line;
  void *next;
};
void *gpio_run(void *ptr)
{
  struct ts_gpio *g = ptr;
  //struct gpiod_chip *chip = NULL;
  int old = 0, new = 0;
  struct gpiod_line *line = g->line;
  while (1) {
    new = gpiod_line_get_value(line);
    if (new != old) {
      fprintf(stderr, "now:%d", new);
      g->value = new;
      old = new;
    }
    usleep(loop_u_time);
  }
}
void *http_send(const char *method, const char *uri, const char *data)
{
  size_t data_len = strlen(data);

  wget_http_connection *conn = NULL;
  wget_http_request *req;
  wget_http_response *resp;
  wget_iri *iri;

  printf("[DEBUG] [L%d f-%s] method:%s url:%s\n", __LINE__, __func__, method, uri);
  iri = wget_iri_parse(uri, NULL);
  req = wget_http_create_request(iri, method);
  wget_http_add_header(req, "Connection", "keepalive");
  if (data) {
   // printf("[DEBUG] [L%d f-%s] body:%s\n", __LINE__, __func__, post_data);
    //wget_http_request_set_body(req, "application/x-www-form-urlencoded",
    wget_http_request_set_body(req, "application/xml",
        wget_memdup(data, data_len), data_len);
  }
  wget_http_open(&conn, iri);
  if (conn) {
    if (!wget_http_send_request(conn, req)) {
      resp = wget_http_get_response(conn);
      if (resp && (resp->body != NULL)) {
        printf("reason:%s code:%d \n", resp->reason, resp->code);
        printf("data:%s\n", resp->body->data);
        //res = calloc(1, resp->body->length+2);
        //memcpy(res, resp->body->data, resp->body->length);
        wget_http_free_response(&resp);
      }
    }
  }
  wget_http_free_request(&req);
  wget_iri_free(&iri);
  wget_http_close(&conn);
//  wget_global_deinit();
  //printf("[DEBUG]L%d f-%s res:%s\n", __LINE__, __func__, (char *)res);
  return NULL;
}
int main (int argc, char **argv)
{
  char *uri = NULL;
  pthread_t thread;
  struct ts_gpio *g = NULL, *now;
  xmlDocPtr doc;
  xmlNodePtr root_node, /*robot_node, motor_node, */gpio_node;
  xmlChar *xml_char = NULL;
  char *filename;
  if ((argc == 3) && !strcmp(argv[1], "-c")) {
    filename = argv[2];
  } else {
    printf("Usage: %s [OPTION]... [FILE]...\n\
%s\n\
-c\tconfig file\n\
Examples:\n\
\t%s -c config.xml\n", SOFTWARE_NAME, SOFTWARE_NAME, SOFTWARE_NAME);
    exit(1);
  }
  if (access(filename, F_OK) == 0) {
    doc = xmlParseFile(filename);
    printf("[DEBUG]xml_driver__file:%s\n", filename);
  } else {
    printf("[----ERROR] no %s\n", filename);
    exit(1);
   // return NULL;
  }
  char *cmd = NULL;
  root_node = xmlDocGetRootElement(doc);
  xml_char = xmlGetProp(root_node, BAD_CAST "uri");
  uri = (char *)xml_char;
  gpio_node = xmlFirstElementChild(root_node);
  while (gpio_node) {
    struct ts_gpio *gpio = calloc(1, sizeof(*gpio));
    if (!g) {
      g = gpio;
    } else {
      now = g;
      while (now->next) {
        now = now->next;
      }
      now->next = gpio;
    } 
    int num, offset;
    xml_char = xmlGetProp(gpio_node, BAD_CAST "name");
    gpio->name = (char *)xml_char;
    xml_char = xmlGetProp(gpio_node, BAD_CAST "chipNum");
    num = atoi((char *)xml_char);
    xmlFree(xml_char);
    xml_char = xmlGetProp(gpio_node, BAD_CAST "lineOffset");
    offset = atoi((char *)xml_char);
    xmlFree(xml_char);
    printf("num:offset %d:%d\n", num, offset);
    struct gpiod_chip *chip = NULL;
    struct gpiod_line *line = NULL;
    chip = gpiod_chip_open_by_number(num);
    if (!chip) {
      fprintf(stderr, "L%d", __LINE__);
      return -1;
    }
    line = gpiod_chip_get_line(chip, offset);
    if (!line) {
      fprintf(stderr, "request output");
      return -1;
    }
    int ret;
    ret = gpiod_line_request_output(line, "example", 0);
//        GPIOD_LINE_ACTIVE_STATE_LOW);
    if (ret != 0) {
      printf("%s %d %s:%d\n",
          __FILE__, __LINE__, __func__, ret);
      return false;
    }
    gpio->line = line;
    pthread_create(&thread, NULL, gpio_run, gpio);
    pthread_detach(thread);
    gpio_node = xmlNextElementSibling(gpio_node);
  }
  char *cmdStop = "stop";
  while (1) {
    now = g;
    cmd = NULL;
    while (now->next) {
      if (now->value) {
        cmd = now->name;
        break;
      }
      now = now->next;
    }
    if (!cmd) {
      cmd = cmdStop;
    }
    char xml[1024];
    snprintf(xml, sizeof(xml),
        "<dev><dev percent='1' cmd='%s'/dev></dev>", cmd);
    http_send("POST", uri, xml); 
    usleep(loop_u_time);
  }
}

